package de.slothsoft.commons.swing.window;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Window;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import de.slothsoft.commons.BoxingUtil;
import de.slothsoft.commons.res.CommonImages;
import de.slothsoft.commons.res.CommonMessages;

public class ConsoleDialog extends AbstractDialog {

	private static final long serialVersionUID = 1L;

	private JTextArea console;
	private PrintStream originalSystemOut;
	private PrintStream originalSystemErr;

	public ConsoleDialog(Window parent) {
		super((Window) null, ButtonType.CLOSE);

		setTitle(CommonMessages.getString("ConsoleDialog.title"));
		setDefaultCloseOperation(HIDE_ON_CLOSE);
		setIconImage(CommonImages.get(CommonImages.OBJECT_CONSOLE).getImage());
		setModal(false);
	}

	@Override
	protected void createLayout() {
		super.createLayout();
		setSize(600, 500);
		centerDialog();
	}

	@Override
	protected void createMainPanel(JPanel mainPanel) {

		this.console = new JTextArea();
		this.console.setEditable(false);
		this.console.setBackground(Color.WHITE);

		mainPanel.setLayout(new BorderLayout());
		mainPanel.add(new JScrollPane(this.console), BorderLayout.CENTER);

		this.originalSystemOut = System.out;
		this.originalSystemErr = System.err;

		PrintStream consoleStream = new PrintStream(new JEditorPaneStream());
		System.setOut(consoleStream);
		System.setErr(consoleStream);
	}

	public void unhookFromSystemOut() {

		System.setOut(this.originalSystemOut);
		System.setErr(this.originalSystemErr);
	}

	public JTextArea getConsole() {
		return this.console;
	}

	public PrintStream getOriginalSystemErr() {
		return this.originalSystemErr;
	}

	public PrintStream getOriginalSystemOut() {
		return this.originalSystemOut;
	}

	/*
	 * 
	 */

	class JEditorPaneStream extends StringOutputStream {

		@Override
		public void writeLine(String line) {
			getConsole().append(line);
			getOriginalSystemOut().print(line);
		}

	}

	abstract class StringOutputStream extends OutputStream {

		private final List<Byte> bytes = new ArrayList<Byte>();

		@Override
		public void write(int b) throws IOException {
			if (b != '\r') {
				// ignore this, because we won't need it
				this.bytes.add(Byte.valueOf((byte) b));
				if (b == '\n') {
					writeLine(new String(BoxingUtil.boxBigToSmallBytes(this.bytes.toArray(new Byte[0]))));
					this.bytes.clear();
				}
			}
		}

		public abstract void writeLine(String line);
	}

}
